package com.ideaaedi.springcloud.jd.commonspring.validator;

import com.ideaaedi.commonds.exception.ValidateException;
import com.ideaaedi.commonds.validate.Validator;
import com.ideaaedi.springcloud.jd.commonds.constant.BaseConstant;
import com.ideaaedi.springcloud.jd.commonds.entity.BaseCodeMsgEnum;
import com.ideaaedi.springcloud.jd.commonds.exception.BaseException;
import com.ideaaedi.springcloud.jd.commonspring.util.JdContextUtil;
import org.springframework.lang.NonNull;
import org.springframework.util.CollectionUtils;

import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 系统校验器
 *
 * @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img
 * src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
 * @since 2021.0.5.B
 */
public interface SysValidator<T> extends Validator<T> {
    
    @Override
    default void validate() throws ValidateException {
        throw new UnsupportedOperationException();
    }
    
    @Override
    default void validate(Supplier<T> supplier) throws ValidateException {
        throw new UnsupportedOperationException();
    }
    
    @Override
    default void validate(Supplier<T> supplier, Function<T, Boolean> function) throws ValidateException {
        throw new UnsupportedOperationException();
    }
    
    @Override
    default boolean validateAndGet() {
        throw new UnsupportedOperationException();
    }
    
    @Override
    default boolean validateAndGet(Supplier<T> supplier) {
        throw new UnsupportedOperationException();
    }
    
    @Override
    default boolean validateAndGet(Supplier<T> supplier, Function<T, Boolean> function) {
        throw new UnsupportedOperationException();
    }
    
    /**
     * 校验当前用户能修改/删除指定租户的数据
     * <p>
     * 提示：在update时，租户插件哪里会对数据范围进行控制，是不会修改到自己可以修改的范围外的数据的。
     *      此方法主要用于那些需要错误提示的api（租户插件会过滤数据，但不会因为数据范围不匹配而报错）、或者是那些忽略了租户插件的update操作
     * </p>
     *
     * @param tenant 要操作的数据所在的租户
     *
     * @throws BaseException 当当前用户不能修改/删除指定租户的数据时抛出
     */
    static void verifyCouldUpdateThisTenant(@NonNull String tenant) {
        Objects.requireNonNull(tenant, "tenant should not be null.");
        LinkedHashSet<String> updateTenantSet = JdContextUtil.currUserDataScopeUpdate();
        if (!CollectionUtils.isEmpty(updateTenantSet)) {
            boolean hasPermission = updateTenantSet.stream().anyMatch(tenant::startsWith);
            if (hasPermission) {
                return;
            }
        }
        throw new BaseException(String.format("tenant -> '%s', updateTenantSet -> '%s'", tenant, updateTenantSet), BaseCodeMsgEnum.RELATED_DATA_EXCEED_CURR_USER_DATA_SCOPE);
    }
    
    /**
     * 校验能删除指定的数据
     *
     * @param id 要校验的数据id
     *
     * @throws BaseException 当试图删除系统内置数据时
     */
    static void verifyCouldDelThisId(@NonNull Number id) {
        Objects.requireNonNull(id, "id cannot be null.");
        if (id.longValue() <= BaseConstant.SYS_INTERNAL_DATA_ID_EQ) {
            throw new BaseException(BaseCodeMsgEnum.SYSTEM_INTERNAL_DATA_NON_ALLOW_UPDATE);
        }
    }
}
